// 版权归Epic Games, Inc.所有。保留所有权利。

#include "LyraPlayerInput.h"
#include "Performance/LatencyMarkerModule.h"
#include "Settings/LyraSettingsLocal.h"

/**
 * 构造函数。
 */
ULyraPlayerInput::ULyraPlayerInput()
	: Super() // 调用父类构造函数
{
	// 不要在CDO上绑定任何设置委托，否则会有常量绑定的监听器
	// 并且它甚至不会做任何事情，因为它不会被勾选/处理输入
	if (HasAnyFlags(RF_ClassDefaultObject | RF_ArchetypeObject)) // 如果是类默认对象或原型对象
	{
		return;
	}
	
	BindToLatencyMarkerSettingChange(); // 绑定到延迟标记设置更改
}

/**
 * 析构函数。
 */
ULyraPlayerInput::~ULyraPlayerInput()
{
	UnbindLatencyMarkerSettingChangeListener(); // 解绑延迟标记设置更改监听器
}

/**
 * 输入键处理。
 * @param Params 输入键事件参数
 * @return 处理结果
 */
bool ULyraPlayerInput::InputKey(const FInputKeyEventArgs& Params)
{
	const bool bResult = Super::InputKey(Params); // 调用父类输入键处理

	// 注意：由于Lyra仅支持"Reflex"插件处理延迟标记，
	// 我们可以使用#if PLATFORM_DESKTOP将其在其他平台上排除以节省资源。然而，为了
	// 同一项目的可扩展性，我们不会这样做。
	ProcessInputEventForLatencyMarker(Params); // 处理输入事件的延迟标记

	return bResult; // 返回处理结果
}

/**
 * 处理输入事件的延迟标记。
 * @param Params 输入键事件参数
 */
void ULyraPlayerInput::ProcessInputEventForLatencyMarker(const FInputKeyEventArgs& Params)
{
	if (!bShouldTriggerLatencyFlash) // 如果不应该触发延迟闪烁
	{
		return;
	}
	
	// 在左键按下时闪烁延迟标记
	if (Params.Key == EKeys::LeftMouseButton) // 如果是左键
	{
		// 获取所有延迟标记模块
		TArray<ILatencyMarkerModule*> LatencyMarkerModules = IModularFeatures::Get().GetModularFeatureImplementations<ILatencyMarkerModule>(ILatencyMarkerModule::GetModularFeatureName());

		// 遍历所有延迟标记模块
		for (ILatencyMarkerModule* LatencyMarkerModule : LatencyMarkerModules)
		{
			// TRIGGER_FLASH是7
			LatencyMarkerModule->SetCustomLatencyMarker(7, GFrameCounter); // 设置自定义延迟标记
		}
	}
}

/**
 * 绑定到延迟标记设置更改。
 */
void ULyraPlayerInput::BindToLatencyMarkerSettingChange()
{
	// 如果平台不支持延迟标记，直接返回
	if (!ULyraSettingsLocal::DoesPlatformSupportLatencyMarkers())
	{
		return;
	}
	
	ULyraSettingsLocal* Settings = ULyraSettingsLocal::Get(); // 获取本地设置
	if (!Settings) // 如果设置无效
	{
		return;
	}

	// 绑定延迟闪烁指示器设置更改事件
	Settings->OnLatencyFlashInidicatorSettingsChangedEvent().AddUObject(this, &ThisClass::HandleLatencyMarkerSettingChanged);

	// 初始化设置并确保输入延迟模块已启用
	HandleLatencyMarkerSettingChanged();
}

/**
 * 解绑延迟标记设置更改监听器。
 */
void ULyraPlayerInput::UnbindLatencyMarkerSettingChangeListener()
{
	ULyraSettingsLocal* Settings = ULyraSettingsLocal::Get(); // 获取本地设置
	if (!Settings) // 如果设置无效
	{
		return;
	}

	// 移除所有此对象的延迟闪烁指示器设置更改事件
	Settings->OnLatencyFlashInidicatorSettingsChangedEvent().RemoveAll(this);
}

/**
 * 处理延迟标记设置更改。
 */
void ULyraPlayerInput::HandleLatencyMarkerSettingChanged()
{
	// 确保我们只在支持延迟标记的平台上收到此回调
	ensure(ULyraSettingsLocal::DoesPlatformSupportLatencyMarkers());
	
	const ULyraSettingsLocal* Settings = ULyraSettingsLocal::Get(); // 获取本地设置
	if (!Settings) // 如果设置无效
	{
		return;
	}

	// 根据设置更改启用或禁用所有标记模块的延迟闪烁
	bShouldTriggerLatencyFlash = Settings->GetEnableLatencyFlashIndicators(); // 获取是否启用延迟闪烁指示器
	
	// 获取所有延迟标记模块
	TArray<ILatencyMarkerModule*> LatencyMarkerModules = IModularFeatures::Get().GetModularFeatureImplementations<ILatencyMarkerModule>(ILatencyMarkerModule::GetModularFeatureName());
	// 遍历所有延迟标记模块
	for (ILatencyMarkerModule* LatencyMarkerModule : LatencyMarkerModules)
	{
		LatencyMarkerModule->SetFlashIndicatorEnabled(bShouldTriggerLatencyFlash); // 设置闪烁指示器启用状态
	}
}